#!/bin/sh
####
##	fnordsense v0.2 :: indicate presense within muCCC hackerspace
#	Copyright (c) 2007 CCC Munich, http://muc.cccc.de/fnordsense
#
# bootstrap
#
export PATH="~/bin:$PATH:.";
perl -e '' || (
  echo "$0 ERROR: Can't find perl interpreter in $PATH!" 1>&2
  echo "Add your perl path to the list at the top of this $0 file." 1>&2
  exit 1
)
perl -x "$0" $@
exit $?
#
# initialize
#
#!perl
use strict;
use Storable;
use LWP::UserAgent;
&loadProgramMeta();
#
# parse command line
#
use Getopt::Std;
our( %Conf, %opts );
getopts( 'Cdhqvc:i:l:', \%opts );
&showChangeLog()    if $opts{'C'};
$Conf{'count'     }  = $opts{'c'};
if( $opts{'i'} and $opts{'i'} =~ /^url=\"?(.+)\"?$/i ) {
  $Conf{'inputUrl'}  = $1;
} elsif ( $opts{'i'} and $opts{'i'} =~ /^exe=\"?(.+)\"?$/i ) {
  $Conf{'inputExe'}  = $1;
}
$Conf{'diagnostics'} = $opts{'d'};
$Conf{'quiet'      } = $opts{'q'};
$Conf{'regex'      } = $opts{'t'};
$Conf{'logFile'    } = $opts{'l'};
&showHelp() if (
  (
    $opts{'h'} or
    $opts{'v'}
  ) or ! (
    (
      $Conf{'inputUrl'} or 
      $Conf{'inputExe'}
    )  and
    $Conf{'count'}
  )
);
undef %opts;
#
# debug mode?
#
if( $Conf{'diagnostics'} ) {
  use utf8;
  use warnings;
  use diagnostics;
}
&debug( 'initialized' );
#
#
#
print &getCopyright() if(
  (
    $Conf{'checkUrl'   } or
    $Conf{'help'       } or
    $Conf{'diagnostics'}
  ) and ! $Conf{'quiet'}
);
&main();
#
# returns copyright string
#
sub getCopyright { return <<COPYRIGHT;
####
##      $Conf{progName} v$Conf{version} :: $Conf{description}
#       Copyright (c) $Conf{copyrightYear} $Conf{copyrightHolder}, $Conf{www}

COPYRIGHT
}
#
# wrapper for changelog message
#
sub showChangeLog {
  print &getCopyright() . &getChangeLog();
  exit 0;
}
#
# wrapper for help message
#
sub showHelp {
  my @changes = split /\nv/, "\n" . &getChangeLog();
  print STDERR &getCopyright() . &getUsage();
  unless( $#changes == -1 ) {
    print STDERR "\nCHANGELOG:";
    for( my $i = 1; $i > -1; $i-- ) {
      next if $#changes <= $i;
      print STDERR "\nv" . $changes[ $#changes - $i ];
    }
  }
  exit 0;
}
#
# logs log messages with lvl error
#
sub error {
  return if $#_ == -1;
  warn &_log( 'ERROR', \@_, ( caller( 1 ) )[3] );
  exit 1;
}
#
# logs log messages with lvl alert
#
sub alert {
  return if $#_ == -1;
  warn &_log( 'ALERT', \@_, ( caller( 1 ) )[3] );
}
#
# logs log messages with lvl info
#
sub info {
  return if $#_ == -1;
  my $text = &_log( 'INFO', \@_, ( caller( 1 ) )[3] );
  print $text unless $Conf{'quiet'};
}
#
# logs log messages with lvl debug
#
sub debug {
  return unless $Conf{'diagnostics'};
  return if $#_ == -1;
  my $text = &_log( 'DEBUG', \@_, ( caller( 1 ) )[3] );
  print $text unless $Conf{'quiet'};
}
#
# backend function for logging messages
#
sub _log {
  #
  # build log message
  #
  my( $level, $caller ) = ( $_[0], $_[2] );
  my @messages = @{ $_[1] };
  $caller = 'main::unknown' unless $caller;
  $caller =~ s/main\:\://o;
  my $logMesg;
  my $time = localtime();
  $time =~ s/^\w+\ //o;
  $time =~ s/\ \d+$//o;
  #
  # verbose output
  # May 19 16:00:07 fnordsense[25784]/checkUrl   INFO : retrieving url ...
  #
  if( $Conf{'diagnostics'} ) {
    foreach my $mesg ( @messages ) {
      $logMesg .= sprintf(
        "$time $Conf{progName}\[$$\]/%-11s %-5s: %s\n",
        $caller,
        $level,
        $mesg
      );
    }
  #
  # normal output
  # May 19 16:00:07 INFO : retrieving url ...
  #
  } else {
    foreach my $mesg ( @messages ) {
      $logMesg .= sprintf( "$time %-5s: $mesg\n", $level );
    }
  }
  #
  # write log file
  #
  if( $Conf{'logFile'} ) {
    open LOG, '>>', $Conf{logFile}
      or die "Can't open log for writing: $!", @messages;
    print LOG $logMesg;
    close LOG or die "Can't write to log: $!", @messages;
  }
  return $logMesg;
}
#
# meta information about this program
#
sub loadProgramMeta {
  $Conf{'version'        } = '0.02';
  $Conf{'description'    } = "indicate presense withing muCCC hackerspace";
  $Conf{'progName'       } = $1 if $0 =~ /\/?([^\/]+)$/o;
  $Conf{'www'            } = "http://muc.ccc.de/$Conf{progName}";
  $Conf{'copyrightHolder'} = 'CCC Munich';
  $Conf{'copyrightYear'  } = '2007';
}
#
# keep track of your changes...
#
sub getChangeLog { return <<'CHANGELOG';
v0.02 :: 2007-11-04 :: ssc@unixgu.ru
- continued working on v0.01, wlan seems to work now via url input =)
v0.01 :: 2007-10-29 :: ssc@unixgu.ru
- started working on implementation with Url and Regex
CHANGELOG
}
#
# documents synopsis and usage information
#
sub getUsage{ return <<USAGE;
SYNOPSIS: [-Cdhqv ] -c [mac-802|mac-ob] -i [url|exe]="foo"  [-l file]
-C Changelog     -d perl Diagnostics   -hv show this Help   -q be Quiet    
-c Count stuff   -i Input src          -l  Log to file

input URL =~ http[s]://[username[:password]@]host.com/page
input EXE =~ ifconfig --foo eth0
mac-802   =~  Ethernet MAC addresses
mac-ob    =~ OpenBeacon MAC addresses
See "man 1 fnordsense" for details.
USAGE
}
#
# main part of this program
#
sub main {
  #
  # check input source
  #
  my $content;
  if( $Conf{'inputUrl'} ) {
    $content = &checkUrl( $Conf{'inputUrl'} );
    &info( 'checked URL input source ' . $Conf{'inputUrl'} );
  } elsif( $Conf{'inputExe'} ) {
    &error( 'TODO: code it' );
    &info( 'checked EXE input source' . $Conf{'inputExe'} );
  } else {
    &error( 'unsupported input source!' );
  }
  #
  # count results
  #
  my $count;
  if( $Conf{'count'} eq 'mac-802' ) {
    $count = &countMac802( $content );
    &info( 'counted Ethernet MAC addresses: ' . $count );
  } elsif( $Conf{'count'} eq 'mac-ob' ) {
    &error( 'TODO: code it' );
    #$count = &countMacOb( $content );
    &info( 'counted OpenBeacon MAC addresses: ' . $count );
  } else {
    &error( 'unsupported counting scheme:' . $Conf{'count'} );
  }
}
#
# counts number of Ethernet MAC adresses in a given string
#
sub countMac802 {
  &info( 'counting Ethernet MAC addresses ...' );
  my $string = $_[0];
  my @ar = split( /[^\dA-Ga-g\:\-](?:[\dA-Ga-g][\:\-]?){5}[\dA-Ga-g][^\dA-Ga-g\:\-]/, $string );
  return( $#ar ) unless $ar[0] eq $string;
}
#
# retrieves content from URL and strips xml/html foo
#
sub checkUrl {
  &info( 'checking URL ...' );
  my $url = $_[0];
  $Conf{'www'} = LWP::UserAgent->new(
    'agent'         => "$0/$Conf{'version'}",
    'timeout'       => 23
  );
  $Conf{'www'}->env_proxy;
  my $resp = $Conf{'www'}->get($url);
  &alert("not successfull exit") unless $resp->is_success();
  my $content = $resp->content();
  #
  # clean from XML
  #
  $content =~ s/\r//go;
  $content =~ s/\<(?:link|title)\>([^\<]+)\<\/(?:link|title)\>/$1\n/go;
  $content =~ s/(?:\<[^\>]*\>|\&lt\;[^\&]+\&gt\;|\&\w{2,4}\;|[\=\-\_]{3,})//go;
  $content =~ s/(?:\n\s+|\n\s*\n)/\n/go;
  $content =~ s/\+/\ /go;
  $content = "\n$content" unless $content =~ /^\n/o;

  return $content; 
}
